package io.noties.markwon.plugin.typogram.bean


/**
 *
 * @author Efstathios Sideris
 */
class GridPatternGroup : ArrayList<GridPattern>() {
    fun areAllMatchedBy(grid: TextGrid): Boolean {
        val it: Iterator<GridPattern> = iterator()
        while (it.hasNext()) {
            val pattern = it.next()
            if (!pattern.isMatchedBy(grid)) return false
        }
        return true
    }

    fun isAnyMatchedBy(grid: TextGrid): Boolean {
        val it: Iterator<GridPattern> = iterator()
        while (it.hasNext()) {
            val pattern = it.next()
            if (pattern.isMatchedBy(grid)) return true
        }
        return false
    }

    fun add(vararg patterns: GridPattern) {
        for (p in patterns) add(p)
    }

    companion object {
        //TODO: define criteria for on-line type?
        val cornerCriteria = GridPatternGroup()
        val normalCornerCriteria = GridPatternGroup()
        val roundCornerCriteria = GridPatternGroup()
        val corner1Criteria = GridPatternGroup()
        val corner2Criteria = GridPatternGroup()
        val corner3Criteria = GridPatternGroup()
        val corner4Criteria = GridPatternGroup()
        val normalCorner1Criteria = GridPatternGroup()
        val normalCorner2Criteria = GridPatternGroup()
        val normalCorner3Criteria = GridPatternGroup()
        val normalCorner4Criteria = GridPatternGroup()
        val roundCorner1Criteria = GridPatternGroup()
        val roundCorner2Criteria = GridPatternGroup()
        val roundCorner3Criteria = GridPatternGroup()
        val roundCorner4Criteria = GridPatternGroup()
        val intersectionCriteria = GridPatternGroup()
        val TCriteria = GridPatternGroup()
        val inverseTCriteria = GridPatternGroup()
        val KCriteria = GridPatternGroup()
        val inverseKCriteria = GridPatternGroup()
        val crossCriteria = GridPatternGroup()
        val stubCriteria = GridPatternGroup()
        val verticalLinesEndCriteria = GridPatternGroup()
        val horizontalLinesEndCriteria = GridPatternGroup()
        val linesEndCriteria = GridPatternGroup()
        val crossOnLineCriteria = GridPatternGroup()
        val horizontalCrossOnLineCriteria = GridPatternGroup()
        val verticalCrossOnLineCriteria = GridPatternGroup()
        val starOnLineCriteria = GridPatternGroup()
        val horizontalStarOnLineCriteria = GridPatternGroup()
        val verticalStarOnLineCriteria = GridPatternGroup()
        val loneDiagonalCriteria = GridPatternGroup()

        init {
            val crossPattern1 = GridPattern(
                ".6.",
                "4+8",
                ".2."
            )
            crossCriteria.add(crossPattern1)
            val KPattern1 = GridPattern(
                ".6.",
                "%4+8",
                ".2."
            )
            KCriteria.add(KPattern1)
            val inverseKPattern1 = GridPattern(
                ".6.",
                "4+%8",
                ".2."
            )
            inverseKCriteria.add(inverseKPattern1)
            val TPattern1 = GridPattern(
                ".%6.",
                "4+8",
                ".2."
            )
            TCriteria.add(TPattern1)
            val inverseTPattern1 = GridPattern(
                ".6.",
                "4+8",
                ".%2."
            )
            inverseTCriteria.add(inverseTPattern1)


            // ****** normal corners *******
            val normalCorner1Pattern1 = GridPattern(
                ".[.",
                "~+(",
                ".^."
            )
            normalCorner1Criteria.add(normalCorner1Pattern1)
            val normalCorner2Pattern1 = GridPattern(
                ".[.",
                "(+~",
                ".^."
            )
            normalCorner2Criteria.add(normalCorner2Pattern1)
            val normalCorner3Pattern1 = GridPattern(
                ".^.",
                "(+~",
                ".[."
            )
            normalCorner3Criteria.add(normalCorner3Pattern1)
            val normalCorner4Pattern1 = GridPattern(
                ".^.",
                "~+(",
                ".[."
            )
            normalCorner4Criteria.add(normalCorner4Pattern1)

            // ******* round corners *******
            val roundCorner1Pattern1 = GridPattern(
                ".[.",
                "~/4",
                ".2."
            )
            roundCorner1Criteria.add(roundCorner1Pattern1)
            val roundCorner2Pattern1 = GridPattern(
                ".[.",
                "4\\~",
                ".2."
            )
            roundCorner2Criteria.add(roundCorner2Pattern1)
            val roundCorner3Pattern1 = GridPattern(
                ".6.",
                "4/~",
                ".[."
            )
            roundCorner3Criteria.add(roundCorner3Pattern1)
            val roundCorner4Pattern1 = GridPattern(
                ".6.",
                "~\\8",
                ".[."
            )
            roundCorner4Criteria.add(roundCorner4Pattern1)

            //stubs
            val stubPattern1 = GridPattern(
                "!^!",
                "!+!",
                ".!."
            )
            stubCriteria.add(stubPattern1)
            val stubPattern2 = GridPattern(
                "!^!",
                "!+!",
                ".-."
            )
            stubCriteria.add(stubPattern2)
            val stubPattern3 = GridPattern(
                "!!.",
                "(+!",
                "!!."
            )
            stubCriteria.add(stubPattern3)
            val stubPattern4 = GridPattern(
                "!!.",
                "(+|",
                "!!."
            )
            stubCriteria.add(stubPattern4)
            val stubPattern5 = GridPattern(
                ".!.",
                "!+!",
                "!^!"
            )
            stubCriteria.add(stubPattern5)
            val stubPattern6 = GridPattern(
                ".-.",
                "!+!",
                "!^!"
            )
            stubCriteria.add(stubPattern6)
            val stubPattern7 = GridPattern(
                ".!!",
                "!+(",
                ".!!"
            )
            stubCriteria.add(stubPattern7)
            val stubPattern8 = GridPattern(
                ".!!",
                "|+(",
                ".!!"
            )
            stubCriteria.add(stubPattern8)


            // ****** ends of lines ******
            val verticalLinesEndPattern1 = GridPattern(
                ".^.",
                ".|.",
                ".!."
            )
            verticalLinesEndCriteria.add(verticalLinesEndPattern1)
            val verticalLinesEndPattern2 = GridPattern(
                ".^.",
                ".|.",
                ".-."
            )
            verticalLinesEndCriteria.add(verticalLinesEndPattern2)
            val horizontalLinesEndPattern3 = GridPattern(
                "...",
                "(-!",
                "..."
            )
            horizontalLinesEndCriteria.add(horizontalLinesEndPattern3)
            val horizontalLinesEndPattern4 = GridPattern(
                "...",
                "(-|",
                "..."
            )
            horizontalLinesEndCriteria.add(horizontalLinesEndPattern4)
            val verticalLinesEndPattern5 = GridPattern(
                ".!.",
                ".|.",
                ".^."
            )
            verticalLinesEndCriteria.add(verticalLinesEndPattern5)
            val verticalLinesEndPattern6 = GridPattern(
                ".-.",
                ".|.",
                ".^."
            )
            verticalLinesEndCriteria.add(verticalLinesEndPattern6)
            val horizontalLinesEndPattern7 = GridPattern(
                "...",
                "!-(",
                "..."
            )
            horizontalLinesEndCriteria.add(horizontalLinesEndPattern7)
            val horizontalLinesEndPattern8 = GridPattern(
                "...",
                "|-(",
                "..."
            )
            horizontalLinesEndCriteria.add(horizontalLinesEndPattern8)


            // ****** others *******
            val horizontalCrossOnLinePattern1 = GridPattern(
                "...",
                "(+(",
                "..."
            )
            horizontalCrossOnLineCriteria.add(horizontalCrossOnLinePattern1)
            val verticalCrossOnLinePattern1 = GridPattern(
                ".^.",
                ".+.",
                ".^."
            )
            verticalCrossOnLineCriteria.add(verticalCrossOnLinePattern1)
            val horizontalStarOnLinePattern1 = GridPattern(
                "...",
                "(*(",
                "..."
            )
            horizontalStarOnLineCriteria.add(horizontalStarOnLinePattern1)
            val horizontalStarOnLinePattern2 = GridPattern(
                "...",
                "!*(",
                "..."
            )
            horizontalStarOnLineCriteria.add(horizontalStarOnLinePattern2)
            val horizontalStarOnLinePattern3 = GridPattern(
                "...",
                "(*!",
                "..."
            )
            horizontalStarOnLineCriteria.add(horizontalStarOnLinePattern3)
            val verticalStarOnLinePattern1 = GridPattern(
                ".^.",
                ".*.",
                ".^."
            )
            verticalStarOnLineCriteria.add(verticalStarOnLinePattern1)
            val verticalStarOnLinePattern2 = GridPattern(
                ".!.",
                ".*.",
                ".^."
            )
            verticalStarOnLineCriteria.add(verticalStarOnLinePattern2)
            val verticalStarOnLinePattern3 = GridPattern(
                ".^.",
                ".*.",
                ".!."
            )
            verticalStarOnLineCriteria.add(verticalStarOnLinePattern3)
            val loneDiagonalPattern1 = GridPattern(
                ".%6%7",
                "%4/%8",
                "%3%2."
            )
            loneDiagonalCriteria.add(loneDiagonalPattern1)
            val loneDiagonalPattern2 = GridPattern(
                "%1%6.",
                "%4\\%8",
                ".%2%5"
            )
            loneDiagonalCriteria.add(loneDiagonalPattern2)


            //groups
            intersectionCriteria.addAll(crossCriteria)
            intersectionCriteria.addAll(KCriteria)
            intersectionCriteria.addAll(TCriteria)
            intersectionCriteria.addAll(inverseKCriteria)
            intersectionCriteria.addAll(inverseTCriteria)
            normalCornerCriteria.addAll(normalCorner1Criteria)
            normalCornerCriteria.addAll(normalCorner2Criteria)
            normalCornerCriteria.addAll(normalCorner3Criteria)
            normalCornerCriteria.addAll(normalCorner4Criteria)
            roundCornerCriteria.addAll(roundCorner1Criteria)
            roundCornerCriteria.addAll(roundCorner2Criteria)
            roundCornerCriteria.addAll(roundCorner3Criteria)
            roundCornerCriteria.addAll(roundCorner4Criteria)
            corner1Criteria.addAll(normalCorner1Criteria)
            corner1Criteria.addAll(roundCorner1Criteria)
            corner2Criteria.addAll(normalCorner2Criteria)
            corner2Criteria.addAll(roundCorner2Criteria)
            corner3Criteria.addAll(normalCorner3Criteria)
            corner3Criteria.addAll(roundCorner3Criteria)
            corner4Criteria.addAll(normalCorner4Criteria)
            corner4Criteria.addAll(roundCorner4Criteria)
            cornerCriteria.addAll(normalCornerCriteria)
            cornerCriteria.addAll(roundCornerCriteria)
            crossOnLineCriteria.addAll(horizontalCrossOnLineCriteria)
            crossOnLineCriteria.addAll(verticalCrossOnLineCriteria)
            starOnLineCriteria.addAll(horizontalStarOnLineCriteria)
            starOnLineCriteria.addAll(verticalStarOnLineCriteria)
            linesEndCriteria.addAll(horizontalLinesEndCriteria)
            linesEndCriteria.addAll(verticalLinesEndCriteria)
            linesEndCriteria.addAll(stubCriteria)
        }
    }
}